package com.ht.config.dataAuth;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ht.module.sys.service.ISysRoleAuthService;
import com.ht.module.sys.vo.SysRoleAuth.UserAuthVo;
import com.ht.util.UserUtil;
import lombok.SneakyThrows;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.util.Map;
import java.util.Properties;

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Component
public class DataScopeInterceptor implements Interceptor {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    @SneakyThrows
    public Object intercept(Invocation invocation) {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);

        // 获取 MappedStatement 判断是不是 SELECT
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
            return invocation.proceed();
        }

        BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
        Object parameterObject = boundSql.getParameterObject();

        // 查找是否包含 DataScope 参数
        DataScope dataScope = findDataScopeObject(parameterObject);
        if (dataScope == null) {
            return invocation.proceed();
        }

        String oldSQL = boundSql.getSql();
        StringBuilder newSQL = new StringBuilder();
        if (oldSQL.startsWith("SELECT COUNT")) {
            newSQL = new StringBuilder(oldSQL);
        }else{
            newSQL = new StringBuilder("SELECT * FROM (").append(oldSQL).append(") TOTAL");
        }
        // 获取当前登录用户权限
        ISysRoleAuthService sysRoleAuthService = applicationContext.getBean(ISysRoleAuthService.class);
        UserAuthVo vo = sysRoleAuthService.findByUserId(UserUtil.getUserId());

        if (ObjectUtil.isNotEmpty(vo.getDeptIds()) && !vo.getDeptIds().isEmpty()) {
            newSQL.append(" WHERE TOTAL.")
                    .append(dataScope.getScopeName())
                    .append(" IN ('").append(CollectionUtil.join(vo.getDeptIds(), "','")).append("')");

            newSQL.append(" OR TOTAL.")
                    .append(dataScope.getScopeUser())
                    .append(" IN ('").append(CollectionUtil.join(vo.getUserIds(), "','")).append("')");
        } else {
            newSQL.append(" WHERE 1 = 0");
        }

        // 修改 SQL
        metaObject.setValue("delegate.boundSql.sql", newSQL.toString());
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {
        // 可扩展
    }

    private DataScope findDataScopeObject(Object parameterObj) {
        if (parameterObj instanceof DataScope) {
            return (DataScope) parameterObj;
        } else if (parameterObj instanceof Map) {
            for (Object val : ((Map<?, ?>) parameterObj).values()) {
                if (val instanceof DataScope) {
                    return (DataScope) val;
                }
            }
        }
        return null;
    }
}
